package admin.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import models.CategoryModel;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;

import debug.CategoryDebug;

public class CategoryData {
	private Objectify ofy;
	
	private int limit = 20;
	
	private int page = 1;
	
	public int getLimit() {
		return limit;
	}

	public void setLimit(int limit) {
		this.limit = limit;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public CategoryData() {
		try {
			ObjectifyService.register(CategoryModel.class);
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		ofy = ObjectifyService.begin();
	}
	
	public void insert(CategoryModel category) {
		//Set parents and level
		String parents = "";
		boolean isUpdate = false;
		if (category.getId() != null) {
			isUpdate = true;
		}
		if (category.getParentId() != 0) {
			CategoryModel parentCategory = getCategory(category.getParentId());
			if (parentCategory != null) {
				parents = parentCategory.getParents();
				int level = parentCategory.getLevel() + 1;
				category.setParents(parents);
				category.setLevel(level);
				
			}
		}
		ofy.put(category);
		
		if (category.getParentId() != 0) {
			parents += "," +  category.getId();
		} else {
			parents += category.getId();
		}
		category.setParents(parents);
		ofy.put(category);
	}
	
	public CategoryModel getCategory(long id) {
		CategoryModel category = new CategoryModel();
		try {
			category = ofy.get(new Key<CategoryModel>(CategoryModel.class, id));
		} catch (Exception e) {
			category = null;
		}
		return category;
	}
	
	public ArrayList<CategoryModel> listAll() {
		ArrayList<CategoryModel> categories = new ArrayList<CategoryModel>();
		
		Query<CategoryModel> q = ofy.query(CategoryModel.class).order("parents");
		for (CategoryModel cat: q) {
			categories.add(cat);
		}
		
		return categories;
	}
	
	public ArrayList<CategoryModel> list() {
		ArrayList<CategoryModel> categories = new ArrayList<CategoryModel>();
		
		int start = (page - 1) * limit;
		Query<CategoryModel> q = ofy.query(CategoryModel.class).order("parents").limit(limit).offset(start);
		for (CategoryModel cat: q) {
			categories.add(cat);
		}
		
		return categories;
	}
	
	public ArrayList<CategoryModel> listWithLevel(int level) {
		ArrayList<CategoryModel> categories = new ArrayList<CategoryModel>();
		
		Query<CategoryModel> q = ofy.query(CategoryModel.class).filter("level <=", level);
		for (CategoryModel cat: q) {
			categories.add(cat);
		}
		
		//Sort category
		Collections.sort(categories, new Comparator<CategoryModel>(){
            public int compare(CategoryModel o1, CategoryModel o2) {
            	CategoryModel c1 = (CategoryModel) o1;
            	CategoryModel c2 = (CategoryModel) o2;
               return c1.getParents().compareToIgnoreCase(c2.getParents());
            }
        });
		
		return categories;
	}
	
	public ArrayList<CategoryModel> listByParentCategory(long parentId) {
		ArrayList<CategoryModel> categories = new ArrayList<CategoryModel>();
		
		int start = (page - 1) * limit;
		Query<CategoryModel> q = ofy.query(CategoryModel.class).filter("parentId", parentId).order("parents").limit(limit).offset(start);
		for (CategoryModel cat: q) {
			categories.add(cat);
		}
		
		return categories;
	}
	
	
	public ArrayList<CategoryModel> listNotContainCategory(long id) {
		ArrayList<CategoryModel> categories = new ArrayList<CategoryModel>();
		
		Query<CategoryModel> q = ofy.query(CategoryModel.class).order("parents");
		for (CategoryModel cat: q) {
			if (cat.getId() != id)
				categories.add(cat);
		}
		
		return categories;
	}
	
	public ArrayList<CategoryModel> listParents(long id) {
		ArrayList<CategoryModel> parents = new ArrayList<CategoryModel>();
		CategoryModel category = getCategory(id);
		if (category != null) {
			String[] ids = category.getParents().split(",");
			for (int i = 0; i < ids.length; i++) {
				if (!ids[i].isEmpty()) {
					category = getCategory(Long.parseLong(ids[i]));
					if (category != null) {
						parents.add(category);
					}
				}
			}
		}
		
		return parents;
	}
	
	public ArrayList<CategoryModel> listChildren(long parent) {
		ArrayList<CategoryModel> categories = new ArrayList<CategoryModel>();
		
		Query<CategoryModel> q = ofy.query(CategoryModel.class).filter("parentId", parent);
		for (CategoryModel cat: q) {
			categories.add(cat);
		}

		return categories;
	}
	
	public boolean hasChildren(long id) {
		boolean hasChildren = false;
		Query<CategoryModel> q = ofy.query(CategoryModel.class).filter("parentId", id).limit(1);
		if (q.count() > 0) {
			hasChildren = true;
		}
		
		CategoryModel category = getCategory(id);
		if (category != null && category.getCount() > 0) {
			hasChildren = true;
		}
		
		return hasChildren;
	}
	
	public void update(CategoryModel category) {
		ofy.put(category);
	}
	
	public void delete(CategoryModel category) {
		ofy.delete(category);
	}
	
	public int count() {
		int n  = ofy.query(CategoryModel.class).count();
		return n;
	}
}
